package com.share.tool.mock.web;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.share.common.common.Result;
import com.share.common.utils.ThreadUtil;
import com.share.tool.mock.model.db.DataLog;
import com.share.tool.mock.model.db.HttpVariable;
import com.share.tool.mock.model.dto.DbMockReq;
import com.share.tool.mock.model.dto.DbMockRsq;
import com.share.tool.mock.model.dto.McParam;
import com.share.tool.mock.service.DataLogService;
import com.share.tool.mock.service.DbVariableService;
import com.share.tool.mock.service.HttpVariableService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Enumeration;
import java.util.Map;

@Slf4j
@Api("通用程序")
@ResponseBody
@RestController
public class CoreController {
    @Autowired
    private HttpVariableService mockHttpVariableService;
    @Autowired
    private DbVariableService mockDbVariableService;
    @Autowired
    private DataLogService dataLogService;

    @ApiOperation("生产db数据(随机生成数据-并组装成insert语句)")
    @RequestMapping(value = "/db/gen")
    public Result dbMork(DbMockReq req) {
        DbMockRsq str = mockDbVariableService.dbMork(req);
        return Result.success(str);
    }

    @ApiOperation("生产http数据")
    @RequestMapping(value = "/hp/{code}")
    public Object httpMork(@PathVariable("code") String code, HttpServletRequest request) {
        DataLog dataLog = new DataLog();
        dataLog.setStartTime(new Date());
        log.info("当前请求url={},code={}", request.getRequestURI(), code);
        if (StringUtils.isEmpty(code)) {
            log.error("请求code为空");
            return Result.failure("请求参数异常");
        }

        String method = request.getMethod();
        if ("GET,POST".indexOf(method) < 0) {
            log.error("请求method不支持");
            return Result.failure("请求method不支持");
        }

        HttpVariable morkHttpVariable = mockHttpVariableService.getByCode(code);
        if (morkHttpVariable == null) {
            log.error("请求code={}不存在", code);
            return Result.failure("请求code不存在");
        }

        //组装参数
        JSONObject header = getHeader(request);
        JSONObject serParam = getSerParam(request);
        JSONObject varParam = new JSONObject();
        Object param = getParam(request);
        McParam mcParam = new McParam(header, serParam, param, varParam);
        log.info("请求参数code={},param={}", code, mcParam.get_param());

        //开始遍历替换
        Object reObj = mockHttpVariableService.httpMock(morkHttpVariable, mcParam);
        String str = reObj == null ? null : reObj.toString();
        dataLog.setCreateTime(new Date());
        dataLog.setEndTime(new Date());
        dataLog.setResponse(str);
        dataLog.setRequest(param == null ? null : param.toString());
        dataLog.setCode(code);
        dataLog.setRemoteIp(request.getRemoteHost());
        log.info("响应结果code={},耗时ms={},result={}", code, dataLog.getEndTime().getTime() - dataLog.getStartTime().getTime(), str);

        //异步保存
        ThreadUtil.execute(() -> dataLogService.insertLog(dataLog));

        //格式适配
        String format = morkHttpVariable.getFormat();
        if ("json".equals(format)) {
            return JSON.parseObject(str);
        } else {
            return str;
        }
    }

    //获取其他参数
    private JSONObject getSerParam(HttpServletRequest request) {
        JSONObject appParam = new JSONObject();
        appParam.put("method", request.getMethod());
        appParam.put("contentType", request.getContentType());
        appParam.put("contextPath", request.getContextPath());
        appParam.put("serverPort", request.getServerPort());
        appParam.put("requestURI", request.getRequestURI());
        appParam.put("remoteHost", request.getRemoteHost());
        return appParam;
    }

    //提取请求头信息
    private JSONObject getHeader(HttpServletRequest request) {
        //获取请求头信息
        JSONObject header = new JSONObject();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            String value = request.getHeader(name);
            header.put(name, value);
        }
        return header;
    }

    //提取参数
    private Object getParam(HttpServletRequest request) {
        //get请求参数提取
        Object param = null;
        String method = request.getMethod();
        if ("GET".equals(method)) {
            JSONObject paramGet = null;
            Map<String, String[]> parameterMap = request.getParameterMap();
            if (!CollectionUtils.isEmpty(parameterMap)) {
                paramGet = new JSONObject();
                for (String key : parameterMap.keySet()) {
                    String[] tmpValue = parameterMap.get(key);
                    String value = ArrayUtils.isEmpty(tmpValue) ? null : tmpValue[0];
                    paramGet.put(key, value);
                }
            }
            param = paramGet;
        } else if ("POST".equals(method)) {
            String body = null;
            String contentType = request.getHeader("content-type");
            try {
                ServletInputStream inputStream = request.getInputStream();
                body = IOUtils.toString(inputStream);
            } catch (Exception e) {
                log.error("参数提取异常contentType={}", contentType, e);
            }

            //如果是json则格式化下
            if (contentType != null && contentType.contains("json")) {
                param = JSON.parseObject(body);
            } else {
                param = body;
            }
        }
        return param;
    }
}
